package assignment

import grails.test.*
import grails.validation.ValidationException;
import grails.test.GrailsUnitTestCase;

class PersonTests extends GrailsUnitTestCase {
	protected void setUp() {
		super.setUp()
	}

	protected void tearDown() {
		super.tearDown()
	}

	void testConstructorOK() {
		mockDomain(Person)
		Person p = new Person(firstname:'Julien', lastname:'Mariethoz', email:'julien@mariethoz.com', username:'jm')
		p.validate()
		assertFalse p.hasErrors()
	}

	//try to instantiate a bean without firstname
	void testConstructorNoFirstName() {
		mockDomain(Person)
		Person p=new Person(firstname:'', lastname:'Mariethoz', email:'j@mariethoz.com', username:'jm')
		assertFalse p.validate()
		assertTrue p.hasErrors()
		assert p.errors.getFieldError('firstname').code == 'blank'
	}

	//try to put an invalid email field
	void testConstructorBadEMail() {
		mockDomain(Person)
		Person p=new Person(firstname:'Julien', lastname:'Mariethoz', email:'julien.mariethoz.com', username:'jm')
		assertFalse p.validate();
		assertTrue p.hasErrors();
		assert p.errors.getFieldError('email').code == 'email.invalid'
	}
	

	//cannot instanciate a second Bean with the same email
	void testConstructorDuplicateUsername() {
		mockDomain(Person)
		Person p=new Person(firstname:'Julien', lastname:'Mariethoz', email:'julien@mariethoz.com', username:'jm')
		assert p.save()

		p=new Person(firstname:'Julien', lastname:'Mariethoz', email:'julien@mariethoz.com', username:'jm')
		assertFalse p.validate()
		assert p.errors.getFieldError('username').code == 'unique'
	}

	void testGet(){
		mockDomain(Person)
		Person p=new Person(firstname:'Julien', lastname:'Mariethoz', email:'julien@mariethoz.com', username:'jm')
		p.save(failOnErrror:true)
		def jm_id=p.id

		Person q_1=Person.get(jm_id)
		assertNotNull(q_1)
		assert q_1.email == 'julien@mariethoz.com'

		Person q_2=Person.findByEmail('julien@mariethoz.com')
		assertNotNull(q_2)
		assert q_2.email == 'julien@mariethoz.com'

		q_2=Person.findByFirstname('Julien')
		assertNotNull(q_2)
		assert q_2.email == 'julien@mariethoz.com'
	}

	void testGetMultipleResults(){
		mockDomain(Person, buildFamily())
		Person p=Person.findByFirstname('Hugo')
		assertNotNull p
		assert p.email == 'hugo@mariethoz.com'

		p=Person.findByLastname('Mariethoz')
		//p is not empty, but just the first element fulfilling the request
		assertNotNull p
	}

	void testUpdate(){
		mockDomain(Person, buildFamily())
		assert Person.count() == 4
		Person p = Person.findByEmail('hugo@mariethoz.com')
		assertNotNull p
		p.lastname='Mariethoz'
		p.save()
		Person q = Person.findByEmail('hugo@mariethoz.com')
		assert q.lastname == 'Mariethoz'
	}

	void testDelete(){
		mockDomain(Person, buildFamily())
		assert Person.count() == 4
		Person p=Person.findByEmail('tristan@mariethoz.com')
		assertNotNull p
		p.delete()
		// we should only have 3 members left
		assert Person.count() == 3
		p=Person.findByEmail('tristan@mariethoz.com')
		assertNull p
	}

	void testList() {
		mockDomain(Person, buildFamily())
		assert Person.count() == 4
		Person.list().each{println it.username}
	}

	static def buildFamily(){
		return [
			'Julien',
			'Carole',
			'Hugo',
			'Tristan'
		].collect {
			new Person(firstname:it,
					lastname:'Mariethoz',
					email:"${it.toLowerCase()}@mariethoz.com", 
					username:"${it.substring(0, 0)}m"
					)
		}
	}
}
